﻿//-----------------------------------------------------------------------
// <copyright file="Program.cs" company="Microsoft Corporation">
// Copyright (c) Microsoft Corporation.
// All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// This code released under the terms of the 
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
// </copyright>
// <author>Yogesh M Joshi</author>
// <email>ymjoshi@live.com</email>
// <date>16-May-2011</date>
//-----------------------------------------------------------------------
namespace SmartTag.Application
{
    using System;
    using SmartTag.Application.CommandLine;
    using SmartTag.Application.Tagging;

    /// <summary>
    /// Main program file
    /// </summary>
    public class Program
    {
        #region "Private Fields"

        /// <summary>
        /// Url of the site
        /// </summary>
        private static string siteUrl;

        /// <summary>
        /// Array containing document library names
        /// </summary>
        private static string[] documentLibraries;

        /// <summary>
        /// Array containing column names
        /// </summary>
        private static string[] columns;

        /// <summary>
        /// Number of worker threads
        /// </summary>
        private static int numberOfThreads = 1;

        /// <summary>
        /// Number of words to scan in given document
        /// P.S. This is an approximate count
        /// </summary>
        private static int wordsToScan = 1000;

        /// <summary>
        /// Relevance of the word to be identified for tagging
        /// </summary>
        private static int relevance = 1;

        #endregion

        /// <summary>
        /// Program entry point
        /// </summary>
        /// <param name="args">Command line arguments</param>
        public static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                PrintHelp();
                return;
            }

            // Parse command line arguments
            Arguments commandArgs = new Arguments(args);
            if (VerifyAndParseArgs(commandArgs) == false)
            {
                PrintHelp();
                return;
            }

            Logger.LogMessage("Initializing...");

            // Start tagging
            TaggingEngine engine = new TaggingEngine(siteUrl, documentLibraries, columns, relevance, wordsToScan, numberOfThreads);
            
            Logger.LogMessage("Starting tagging operation...");

            engine.Start();
            
            Logger.LogMessage("Tagging completed successfully.");
        }

        /// <summary>
        /// This method verifies that, valid command line arguments are passed to the application
        /// also, it parses them and initializes appropriate variables
        /// Following are the required arguments
        /// site = WebUrl
        ///  * Optinal params *
        /// doclibs = Name of the lists to be used if not specified all document libraries will be considered
        /// columnnames = "Name of column(s) to tag" -> All tax columns will be tagged in case its empty
        /// threads = "Number of threads" -> Default is 1 thread
        /// wordcount = Number of words to be scanned for given document
        /// relevance = Number of matches for term
        /// </summary>
        /// <param name="args">Command line arguments</param>
        /// <returns>Flag indicating that arguments are valid</returns>
        private static bool VerifyAndParseArgs(Arguments args)
        {
            bool requiredParamsPresent = true;
            string sitename = args["site"];

            // Site name is not given
            if (string.IsNullOrEmpty(sitename))
            {
                Console.WriteLine("Please specify the required -site parameter");
                requiredParamsPresent = requiredParamsPresent && false;
            }

            /* Set the site name */
            siteUrl = sitename;

            /* Fetch the list names */
            string doclibs = args["doclibs"];

            // Check for the document libraries
            if (string.IsNullOrEmpty(doclibs) == false)
            {
                documentLibraries = doclibs.Split(new char[] { ';' });
            }

            // Check for the column names
            string columnnames = args["columnnames"];

            if (string.IsNullOrEmpty(columnnames) == false)
            {
                columns = columnnames.Split(new char[] { ';' });
            }

            // Check for the threads
            string strThreadCount = args["threads"];

            if (string.IsNullOrEmpty(strThreadCount) == false)
            {
                int threads = 0;
                if (int.TryParse(strThreadCount, out threads) == false
                    || threads > 10 || threads < 1)
                {
                    Console.WriteLine("Please enter a valid thread count (Min : 1, Max: 10).");
                    requiredParamsPresent = requiredParamsPresent && false;
                }
                else
                {
                    numberOfThreads = threads;
                }
            }

            // Check for the wordcount option
            string strWordCount = args["wordcount"];
            if (string.IsNullOrEmpty(strWordCount) == false)
            {
                if (int.TryParse(strWordCount, out wordsToScan) == false 
                    || wordsToScan < 100 || wordsToScan > 10000)
                {
                    Console.WriteLine("Please enter a valid value for -wordcount parameter");
                    requiredParamsPresent = requiredParamsPresent && false;
                }
            }

            // Check for the relevece option
            string strRelevance = args["relevance"];
            if (string.IsNullOrEmpty(strRelevance) == false)
            {
                if (int.TryParse(strRelevance, out relevance) == false || relevance < 1 || relevance > 100)
                {
                    Console.WriteLine("Please enter a valid value for -relevance parameter");
                    requiredParamsPresent = requiredParamsPresent && false;
                }
            }

            return requiredParamsPresent;
        }

        /// <summary>
        /// Print the help on console
        /// </summary>
        private static void PrintHelp()
        {
            Console.WriteLine("\nUsage:\n");
            Console.WriteLine("\tsmarttag.exe -<argument> <parameters>\n");
            Console.WriteLine("\nRequired Arguments:\n");
            Console.WriteLine("\t-site\t\t<Url of the site>");
            Console.WriteLine("\nOptional Arguments:\n");
            Console.WriteLine("\t-doclibs\t<Semicomma(;) seperated list of document library names\n\t\t\t(All document libraries if not specified)>");
            Console.WriteLine("\t-columnnames\t<Semicomma(;) seperated list of columnnames\n\t\t\t(All taxonomy columns if not specified)>");
            Console.WriteLine("\t-threads\t<Number of worker threads (Min: 1,Max: 10,Default: 1)>");
            Console.WriteLine("\t-wordcount\t<Number of words to scan from document \n\t\t\t(Min: 100, Max: 10000, Default: 1)>");
            Console.WriteLine("\t-relevance\t<Min number of matches for term\n\t\t\t(Min:1, Max: 100, Default:1)>");
        }
    }
}

